package com.l.shirodemo.shiro;

import com.l.shirodemo.mapper.LoginMapper;
import com.l.shirodemo.pojo.Login;
import com.l.shirodemo.pojo.Role;
import com.l.shirodemo.service.LoginService;
import com.l.shirodemo.service.RoleService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class LoginRealm extends AuthorizingRealm {
    @Autowired
    private LoginService loginService;

    @Autowired
    private RoleService roleService;


    /**
     * 授权
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行了授权11111111111");
//        1、从 PrincipalCollection 中获取信息
        Object primaryPrincipal = principalCollection.getPrimaryPrincipal();
        Login login = (Login) primaryPrincipal;
//        2、利用登录的用户信息来决定当前用户的角色和权限（查询数据库）
        List<Role> roleList = roleService.findByLoginId(login.getId());

        Set<String> roles = new HashSet<>();
//        无论是谁，都有角色权限
//        roles.add("user");
        roleList.forEach(s->{
           roles.add(s.getName());
        });
//        3、创建 SimpleAuthorizationInfo 对象,并设置 roles 属性
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);
//        4、返回SimpleAuthorizationInfo对象
        return info;
    }

    /**
     * 认证
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("执行了认证111111111111111");
//authenticationToken实际是  subject.login(token) 中的token

        // 1、将AuthenticationToken还原为UsernamePasswordToken
        UsernamePasswordToken token=(UsernamePasswordToken)authenticationToken;
        // 2、从UsernamePasswordToken中获取username
        String username = token.getUsername();
        // 3、调用数据库中的方法，查询用户
        Login login = loginService.findByName(username);
        // 4、如果用户不存在，可以抛出unknownaccountexception
        if (login==null){
            return null;//抛出异常 unknownaccountexception
        }
        // 5、根据用户信息，可以抛出其他异常，比如用户锁定异常

        // 6、根据用户情况，构建 AuthenticationInfo 对象并返回，通常使用实现类：SimpleAuthenticationInfo
        //以下参数信息是从数据库中获取的

        // 认证实体信息，可以是username，也可以是用户实体对象
        Object principal = login;
        // credentials：认证凭证，即密码
        Object credentials = login.getPassword();
        // realmName:当前realm 对象的 name，可以直接使用 父类的 getName();
        String realmName = getName();
        //salt 唯一，一般使用登录账号
        ByteSource salt = ByteSource.Util.bytes(username);
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal,credentials,salt,realmName);

        return info;
    }

    public static void main(String[] args) {
        SimpleHash md5 = new SimpleHash("md5", "123456", "lisi", 32);
        System.out.println(md5);
    }
}
